package com.example.demoopengles;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;

/**
 * 
 * @author Fish
 * 
 */
public class MyGLSurfaceRender implements GLSurfaceView.Renderer {

	private static final String TAG = MyGLSurfaceRender.class.getSimpleName();

	private int mProgram;
	
	private int mPositionHandle;
	
	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// TODO Auto-generated method stub
		GLES20.glClearColor(0f, 0f, 0f, 1f);
		mProgram = createProgram();
		
		mTriangle = new Triangle();
		
		mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
		GLES20.glEnableVertexAttribArray(mPositionHandle);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		// TODO Auto-generated method stub
		GLES20.glViewport(0, 0, width, height);
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		// TODO Auto-generated method stub
		// clear the buffer
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
		
		//use the program
		GLES20.glUseProgram(mProgram);
		
		//draw the triangle !!! issue the data from the buffer to the array !
		GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false,0, mTriangle.mBuffer);

		GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
		
	}

	Triangle mTriangle;

	private String mVertexShader = "attribute vec4 vPosition; \n" + "void main() \n" + "{ \n" + "gl_Position = vPosition; \n" + "} \n";

	private String mFragmentShader = "precision mediump float; \n" + "void main() \n" + "{ \n" + "gl_FragColor = vec4(0.0,0.0,1.0,1.0); \n" + "} \n";

	private int createProgram() {
		int program = GLES20.glCreateProgram();
		if (program == 0) {
			return 0;
		}

		GLES20.glAttachShader(program, createShader(GLES20.GL_VERTEX_SHADER, mVertexShader));
		GLES20.glAttachShader(program, createShader(GLES20.GL_FRAGMENT_SHADER, mFragmentShader));

		GLES20.glLinkProgram(program);
		
		Log.i(TAG, "\t program -> "+program);
		return program;
		
	}
	
    private void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, op + ": glError " + error);
            throw new RuntimeException(op + ": glError " + error);
        }
    }

	private int createShader(int shaderType, String souce) {
		Log.v(TAG, "createShader");
		int shader = GLES20.glCreateShader(shaderType);
		if (shader == 0) {
			Log.e(TAG, "Failed to create shader !");
			return 0;
		}

		GLES20.glShaderSource(shader, souce);
		GLES20.glCompileShader(shader);

		int[] status = new int[1];
		GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, status, 0);

		if (status[0] == 0) {
			Log.e(TAG, "\t " + GLES20.glGetShaderInfoLog(shader));
			GLES20.glDeleteShader(shader);
			return 0;
		}

		Log.i(TAG, "\t shader -> "+shader);
		return shader;
	}

	class Triangle {

		private FloatBuffer mVertextBuffer;

		static final int COORDS_PRE_VERTEXT = 3;

		final float triangleCoords[] = { 
				0.0f, 0.5f, 0.0f, 
				-0.5f, -0.5f, 0.0f, 
				0.5f, -0.5f, 0.0f };
		
		
		private FloatBuffer mBuffer;

		public Triangle() {

			ByteBuffer buffer = ByteBuffer.allocateDirect(triangleCoords.length * 4);
			buffer.order(ByteOrder.nativeOrder());
			
			FloatBuffer floatBuffer = buffer.asFloatBuffer();
			floatBuffer.put(triangleCoords);
			floatBuffer.position(0);
			
			mBuffer = floatBuffer;
			
		}
	}

}
